home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / GameKit / gamekit-1 / Animator.m < prev    next >
Text File  |  1995-06-12  |  5KB  |  229 lines

  1. //  Animator.m
  2. //  Object for general timing, animation, and dynamics.
  3. //  Author: R. E. Crandall, Educational Technology Center
  4. //  10-Apr-88
  5. //  Revised by Bluce Blumberg for 0.8, 29-Sep-88
  6. //  Revised for 1.0 by Ali Ozer, 13-Jun-89
  7. //  Revised for 2.0 by Jayson Adams, 14-Oct-90
  8. //
  9. // You may freely copy, distribute and reuse the code in this example.
  10. // NeXT disclaims any warranty of any kind, expressed or implied, as to its
  11. // fitness for any particular use.
  12.  
  13. /*
  14.  *  An 'Animator' controls the timing for your action method of choice.
  15.  *  The object may function as a general timer object; i.e.
  16.  *  graphics are neither expected nor required by the class.
  17.  *  When you create an Animator with +newChronon, you specify
  18.  *  the time interval between calls, the adaptation time constant (see below),
  19.  *  the target to which the method belongs, the action name, whether to 
  20.  *  automatically start up the timing upon creation, and an event mask (if you     
  21.  *  plan to break conditionally out of loops within the action method).
  22.  *
  23.  *  The Animator has adaptive means for adjusting to harsh operating
  24.  *  environments.  An adaptation constant d > 0. will invoke dynamical 
  25.  *  correction of entry times, on-the-fly, so that the desired chronon
  26.  *  will be realized in a real-time sense.
  27.  *
  28.  *  Functionality and applications are discussed in Report ETC-0008.
  29.  */
  30.  
  31. #import <gamekit/Animator.h>
  32.  
  33. #import <appkit/appkit.h>
  34. #import <sys/time.h>
  35. #import <objc/objc-runtime.h>
  36.  
  37.  
  38. @implementation Animator
  39.  
  40. void timerFunction(teNum, now, self)
  41. DPSTimedEntry teNum;
  42. double now;
  43. Animator *self;
  44. {
  45.     gettimeofday(&self->entrytime, NULL);
  46.     if (self->howOften > 0.0) {
  47.     [self adapt];
  48.     }
  49.     
  50.     [self->target perform:self->action with:self];
  51. }
  52.  
  53. - initChronon:(double)dt    /* The time increment desired. */
  54.   adaptation:(double)howoft    /* Adaptive time constant (0.deactivates).*/
  55.   target:(id)targ        /* Target to whom proc belongs. */
  56.   action:(SEL)act        /* The action. */
  57.   autoStart:(int)start        /* Automatic start of timed entry? */
  58.   eventMask:(int)eMask        /* Mask for optional check in "shouldBreak". */
  59. {
  60.     [super init];
  61.     ticking = NO;
  62.     desireddt = dt;
  63.     [self setIncrement:dt];
  64.     [self setAdaptation:howoft];
  65.     [self setTarget:targ];
  66.     [self setAction:act];
  67.     
  68.     if (start) {
  69.     [self startEntry];
  70.     }
  71.     
  72.     mask = eMask;
  73.     [self resetRealTime];
  74.     
  75.     return self;
  76. }
  77.  
  78. - resetRealTime
  79. /* After this call, getDoubleRealTime is the real time that ensues. */
  80.     struct timeval    realtime;
  81.     
  82.     gettimeofday(&realtime, NULL);
  83.     synctime = realtime.tv_sec + realtime.tv_usec / 1000000.0;
  84.     passcounter = 0;
  85.     t0 = 0.0;
  86.     
  87.     return self;
  88. }
  89.  
  90. - (double)getSyncTime
  91. {
  92.     return synctime;
  93. }
  94.  
  95. - (double)getDoubleEntryTime
  96. /* Returns real time since "resetrealTime". */
  97. {
  98.     return (- synctime + entrytime.tv_sec + entrytime.tv_usec / 1000000.0);
  99. }
  100.  
  101. - (double)getDoubleRealTime
  102. /* Returns real time since "resetrealTime". */
  103. {
  104.     struct timeval    realtime;
  105.     struct timezone    tzone;
  106.     
  107.     gettimeofday(&realtime, &tzone);
  108.     return (- synctime + realtime.tv_sec + realtime.tv_usec / 1000000.0);
  109. }
  110.  
  111. - (double)getDouble
  112. {
  113.     return [self getDoubleRealTime];
  114. }
  115.  
  116. - adapt
  117. /* Adaptive time-step algorithm. */
  118. {
  119.     double t;
  120.     
  121.     if (!ticking) {
  122.     return self;
  123.     }
  124.     
  125.     ++passcounter;
  126.     t = [self getDoubleEntryTime];
  127.     
  128.     if (t - t0 >= howOften) {      
  129.     adapteddt *= desireddt * passcounter / (t - t0);
  130.     [self setIncrement:adapteddt];
  131.     [self startEntry];
  132.     passcounter = 0;
  133.     t0 = t;
  134.     }
  135.     return self;
  136. }
  137.   
  138. - setBreakMask:(int)eventMask
  139. {
  140.     mask = eventMask;
  141.     return self;
  142. }
  143.  
  144. - (int)getBreakMask
  145. {
  146.     return mask;
  147. }
  148.  
  149. - (int)isTicking
  150. {
  151.     return ticking;
  152. }
  153.    
  154. - (int)shouldBreak
  155. /* Call this to see if you want to exit a loop in your action method. */
  156. {
  157.     NXEvent    *e, event;
  158.     
  159.     e = [NXApp peekNextEvent:mask
  160.                into:&event
  161.            waitFor:0.0
  162.            threshold:NX_MODALRESPTHRESHOLD + 1];
  163.            
  164.     return (e ? 1: 0);
  165. }
  166.  
  167. - setIncrement:(double)dt
  168. {
  169.     adapteddt = dt;
  170.     interval = dt;
  171.   
  172.     return self;
  173. }
  174.  
  175. - (double)getIncrement
  176. {
  177.     return adapteddt;
  178. }
  179.  
  180. - setAdaptation:(double)oft
  181. {
  182.     howOften = oft;
  183.     return self;
  184. }
  185.  
  186. - setTarget:(id)targ
  187. {
  188.     target = targ;
  189.     return self;
  190. }
  191.  
  192. - setAction:(SEL)aSelector
  193. {
  194.     action = aSelector;
  195.     return self;
  196. }
  197.  
  198. - startEntry
  199.     [self stopEntry];
  200.     teNum = DPSAddTimedEntry(interval, &timerFunction, self,
  201.                      NX_MODALRESPTHRESHOLD+1);
  202.     ticking = YES;
  203.     
  204.     return self;
  205. }
  206.  
  207. - stopEntry
  208. {
  209.     if (ticking) {
  210.     DPSRemoveTimedEntry(teNum);
  211.     }
  212.     ticking = NO;
  213.     
  214.     return self;
  215. }
  216.  
  217. - free
  218. {
  219.     if (ticking) {
  220.     DPSRemoveTimedEntry(teNum);
  221.     }
  222.     
  223.     return [super free];
  224. }
  225.  
  226. @end    
  227.